/**
 * @author: 團長
 * @date: 2013-5-14-下午5:57:39
 */
package net.loyintean.pearlshell.basedb.impl;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import net.loyintean.pearlshell.base.model.ILogInfo;
import net.loyintean.pearlshell.base.model.IResult;
import net.loyintean.pearlshell.base.model.impl.LogInfoFactory;
import net.loyintean.pearlshell.base.model.impl.ResultFactory;
import net.loyintean.pearlshell.basedb.IEditDBService;
import net.loyintean.pearlshell.basedb.IListQueryDBService;
import net.loyintean.pearlshell.basedb.IPagedQueryDBService;
import net.loyintean.pearlshell.basedb.IQueryDBService;
import net.loyintean.pearlshell.basedb.IRemoveDBService;
import net.loyintean.pearlshell.basedb.ISaveDBService;
import net.loyintean.pearlshell.basedb.dao.BaseDao;
import net.loyintean.pearlshell.basedb.dto.BaseDto;
import net.loyintean.pearlshell.basedb.exception.TransactionException;

/**
 * 默认的基础数据库服务实现类
 * <p>
 * 2013年09月18日 团长 增加IBatchDBService接口
 * <p>
 * 2014-8-1 Loy 增加 {@link #editSingleDto(BaseDto)}方法，并且废弃了
 * {@link #editSingleDto(BaseDto)}方法。 v2014-8-1.1.1.0
 * 
 * @author 團長
 * @since 2014-8-1
 * @version 1.1.0
 * @param @{code <T extends BaseDto>}
 */
public class DefaultBaseDBServiceImpl<T extends BaseDto> implements
		IEditDBService<T>, IListQueryDBService<T>, IPagedQueryDBService<T>,
		IQueryDBService<T>, IRemoveDBService<T>, ISaveDBService<T> {

	/**
	 * 日志记录器
	 * 
	 * @author 團長
	 * @since 2013-5-15
	 */
	protected final Logger logger = Logger.getLogger(this.getClass());

	/**
	 * 数据库接口
	 * 
	 * @author 團長
	 * @since 2013-5-14
	 */
	protected BaseDao<T> dao;

	/**
	 * only when the value returned from
	 * {@link BaseDao#insertSingleDto(BaseDto)} is greater then zero, this
	 * method will return an IResult with status of SUCCESS.<br>
	 * it might cause error in iBatis/myBatis with BATCH executor.
	 * 
	 * @author Loy
	 * @since 2014-9-10
	 * @see net.loyintean.pearlshell.basedb.ISaveDBService
	 *      #saveSingleDto(net.loyintean.pearlshell.basedb.dto.BaseDto)
	 */
	@Override
	public IResult<Integer> saveSingleDto(T dto) throws TransactionException {
		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		IResult<Integer> id = ResultFactory.INIT(-1);

		try {
			int result = dao.insertSingleDto(dto);

			if (result > 0) {
				id.success(result);
			} else {
				id.fail(-1, "can't insert correctly with " + dto
						+ " ! rows/id returned is " + result + "!");
			}

		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			throw new TransactionException(e);
		}

		logger.info(logInfo.end("@id=" + id));
		return id;
	}

	/**
	 * only when the value returned from
	 * {@link BaseDao#deleteSingleDto(BaseDto)} is greater then zero, this
	 * method will return an IResult with status of SUCCESS.
	 * 
	 * @author Loy
	 * @since 2014-9-10
	 * @see net.loyintean.pearlshell.basedb.IRemoveDBService
	 *      #removeSingleDto(net.loyintean.pearlshell.basedb.dto.BaseDto)
	 */
	@Override
	public IResult<Integer> removeSingleDto(T dto) throws TransactionException {
		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		IResult<Integer> result = ResultFactory.INIT(-1);

		try {
			int rows = dao.deleteSingleDto(dto);

			if (rows > 0) {
				result.success(rows);
			} else {
				result.fail(0, "nothing removed from db with " + dto + " !");
			}

		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			throw new TransactionException(e);
		}

		logger.info(logInfo.end("@rows=" + result));
		return result;

	}

	/**
	 * only when the value returned from
	 * {@link BaseDao#selectSingleDto(BaseDto)} is not null, this method will
	 * return an IResult with status of SUCCESS.
	 * 
	 * @author Loy
	 * @since 2014-9-10
	 * @see net.loyintean.pearlshell.basedb.IQueryDBService
	 *      #querySingleDto(net.loyintean.pearlshell.basedb.dto.BaseDto)
	 */
	@Override
	public IResult<T> querySingleDto(T dto) throws TransactionException {

		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		IResult<T> result = ResultFactory.INIT();

		try {
			T dbRow = dao.selectSingleDto(dto);

			if (dbRow != null) {
				result.success(dbRow);
			} else {
				result.fail("nothing can be find out from db with " + dto
						+ " !");
			}

		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			throw new TransactionException(e);
		}

		logger.info(logInfo.end("@result=" + result));
		return result;

	}

	/**
	 * only when the value returned from {@link BaseDao#selectDtoList(BaseDto)}
	 * is not null and not empty, this method will return an IResult with status
	 * of SUCCESS.
	 * 
	 * @author Loy
	 * @since 2014-9-10
	 * @see net.loyintean.pearlshell.basedb.IListQueryDBService
	 *      #queryDtoList(net.loyintean.pearlshell.basedb.dto.BaseDto)
	 */
	@Override
	public IResult<List<T>> queryDtoList(T dto) throws TransactionException {

		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		IResult<List<T>> result = ResultFactory.INIT(new ArrayList<T>());

		try {
			List<T> list = dao.selectDtoList(dto);

			if (list != null && !list.isEmpty()) {
				result.success(list);
			} else {
				result.fail("no list can be find out from db with " + dto
						+ " !");
			}

		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			throw new TransactionException(e);
		}

		logger.info(logInfo.end("@result=" + result));
		return result;

	}

	/**
	 * only when the value returned from
	 * {@link BaseDao#selectPagedList(BaseDto)} is not null and not empty, this
	 * method will return an IResult with status of SUCCESS.
	 * 
	 * @author Loy
	 * @since 2014-9-10
	 * @see net.loyintean.pearlshell.basedb.IPagedQueryDBService
	 *      #queryPagedList(net.loyintean.pearlshell.basedb.dto.BaseDto)
	 */
	@Override
	public IResult<List<T>> queryPagedList(T dto) throws TransactionException {

		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		IResult<List<T>> result = ResultFactory.INIT(new ArrayList<T>());

		try {
			List<T> list = dao.selectPagedList(dto);

			if (list != null && !list.isEmpty()) {
				result.success(list);
			} else {
				result.fail("no paged list can be find out from db with " + dto
						+ " !");
			}

		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			throw new TransactionException(e);
		}

		logger.info(logInfo.end("@result=" + result));
		return result;

	}

	/**
	 * only when the value returned from
	 * {@link BaseDao#selectTotalCount(BaseDto)} is not less then zero, this
	 * method will return an IResult with status of SUCCESS.
	 * 
	 * @author Loy
	 * @since 2014-9-10
	 * @see net.loyintean.pearlshell.basedb.IPagedQueryDBService
	 *      #queryTotalCount(net.loyintean.pearlshell.basedb.dto.BaseDto)
	 */
	@Override
	public IResult<Integer> queryTotalCount(T dto) throws TransactionException {

		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		IResult<Integer> result = ResultFactory.INIT(0);

		try {
			int count = dao.selectTotalCount(dto);

			if (count >= 0) {
				result.success(dao.selectTotalCount(dto));
			} else {
				result.fail("an error number returned by dao with " + dto
						+ ", the number is " + count + " !");
			}

		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			throw new TransactionException(e);
		}

		logger.info(logInfo.end("@result=" + result));
		return result;

	}

	/**
	 * call the dao.updateSingleDto(dto). This method has nothing todo with
	 * {@link #editSingleDto(BaseDto)}
	 * 
	 * @author Loy
	 * @since 2014-8-1
	 * @see net.loyintean.pearlshell.basedb.IEditDBService
	 *      #editSingleDto(net.loyintean.pearlshell.basedb.dto.BaseDto)
	 */
	@Override
	public IResult<Integer> editSingleDto(T dto) throws TransactionException {
		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		IResult<Integer> result = ResultFactory.INIT(0);

		try {
			result.success(dao.updateSingleDto(dto));
		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			throw new TransactionException(e);
		}

		logger.info(logInfo.end("@result=" + result));
		return result;

	}

	/**
	 * @param dao
	 *            the {@link #dao }to set
	 */
	public void setDao(BaseDao<T> dao) {
		this.dao = dao;
	}

}
